#include <iostream>
#include <functional>
#include <vector>
#include <memory>
#include <unordered_map>
#include <unistd.h>
using TaskFunc = std::function<void()>;
using ReleaseFunc = std::function<void()>;
class TimerTask//定时器任务
{
public:
    TimerTask(uint64_t id, uint32_t timeout, const TaskFunc& taskCallBack)
        :_id(id)
        ,_timeout(timeout)
        ,_taskCallBack(taskCallBack)
        ,_canceled(false)
    {}
    ~TimerTask()
    {
        if(_canceled == false)//任务没有被取消
        {
            _taskCallBack();//执行任务回调（销毁任务）
        }
        _releaseFunc();
    }
public:
    void SetRelease(const ReleaseFunc& taskCallBack)//TimerWheel类中传入的删除方法，用于删除TimerWheel中保存的定时器std::unordered_map<uint64_t, WeakPtrTask>信息
    {
        _releaseFunc = taskCallBack;
    }
    uint32_t GetTimeout() const
    {
        return _timeout;
    }
    void Cancel()//取消定时任务
    {
        _canceled = true;
    }
private:
    uint64_t _id;//定时器任务对象id
    uint32_t _timeout;//定时任务的超时时间
    bool _canceled;//定时任务是否可以被取消，true表示被取消
    TaskFunc _taskCallBack;//定时器对象要执行的定时任务
    ReleaseFunc _releaseFunc;//TimerWheel类中传入的删除方法
};

using SharedPtrTask = std::shared_ptr<TimerTask>;//相当于typedef
using WeakPtrTask = std::weak_ptr<TimerTask>;//相当于typedef
class TimerWheel//时间轮
{
public:
    TimerWheel()
        :_wheel(_capacity)//包含_capacity个元素的vector
        ,_tick(0)
        ,_capacity(60)
    {}
public:
    void TimerAdd(uint64_t id, uint32_t timeout, const TaskFunc& taskCallBack)//向时间轮添加定时任务(销毁任务)
    {
        SharedPtrTask pt(new TimerTask(id, timeout, taskCallBack));//对定时器任务创建共享指针  
        pt->SetRelease(std::bind(&TimerWheel::RemoveTimer, this, id));//设置移除函数
        _wheel[(_tick + timeout) % _capacity].push_back(pt);//将共享指针插入数组
        _timers[id] = WeakPtrTask(pt);//在unordered_map中填充弱指针，根据共享指针构造一个弱指针，不会让计数器+1
    }
    void TimerRefresh(uint64_t id)//在时间轮中刷新定时任务（在unordered_map找到弱指针，通过弱指针构造共享指针）
    {
        auto it = _timers.find(id);
        if(it == _timers.end())
        {
            return;//在unordered_map中没找到弱指针
        }
        SharedPtrTask pt = it->second.lock();//通过lock获取weak_ptr所管理的对象
        int timeout = pt->GetTimeout();//获取定时任务的初始延时时间
        _wheel[(_tick + timeout) % _capacity].push_back(pt);//将生成的共享指针插入数组
    }
    void TickRun()//秒针滴答，每秒执行一次
    {
        _tick = (_tick + 1) % _capacity;
        _wheel[_tick].clear();//清空指定位置的数组元素，释放数组中所有保存的定时器对象的共享指针
    }
    void TimerCancel(uint64_t id)//取消定时任务
    {
        auto it = _timers.find(id);
        if(it == _timers.end())
        {
            return;//在unordered_map中没找到弱指针
        }
        SharedPtrTask pt = it->second.lock();//通过lock获取weak_ptr所管理的对象
        if(pt)//共享指针pt可能为空
        {
            pt->Cancel();
        }
    }
private:
    void RemoveTimer(uint64_t id)//传入TimerTask类中，作为unordered_map<uint64_t, WeakPtrTask>中任务的删除函数
    {
        auto it = _timers.find(id);
        if(it != _timers.end())
        {
            _timers.erase(it);
        }
    }
private:
    int _capacity;//时间轮的最大刻度（最大延时时间）
    std::vector<std::vector<SharedPtrTask>> _wheel;//轮
    int _tick;//秒针滴答下标，走到哪就释放哪的对象
    std::unordered_map<uint64_t, WeakPtrTask> _timers;//<定时器任务对象id, 弱指针>
}; 

class Test
{
public:
    Test()
    {
        std::cout << "构造函数" << std::endl;
    }
    ~Test()
    {
        std::cout << "析构函数" << std::endl;
    }
};
void DelTest(Test* t)
{
    delete t;
}
int main()
{
    TimerWheel tw;
    Test* t = new Test();
    tw.TimerAdd(888, 5, std::bind(DelTest, t));
    for(int i = 0; i < 5; ++i)
    {
        sleep(1);
        tw.TimerRefresh(888);//刷新定时任务
        tw.TickRun();//向后移动秒针
        std::cout << "刷新了一次定时任务,5秒后才会销毁" << std::endl;
    }
    tw.TimerCancel(888);
    while(1)
    {
        std::cout << "---------------------" << std::endl;
        tw.TickRun();//向后移动秒针
        sleep(1);
    }
    return 0;
}